#pragma once

#include "Delegate.h"

#if !defined _BACKDOOR_NETWORK_
#define _BACKDOOR_NETWORK_


#define NETMSG_MJ_CONTROL 0x1
	#define NETMSG_MN_ALIVE 0x1

#define NETMSG_MJ_FILE 0x2
	#define NETMSG_MN_LISTDIR 0x2

namespace hxc
{

//BOOL PASCAL SocketInitialize();

struct _SocketInitializer
{
    void Initialize();
    void Free();
    class _ThreadPool* tp;
    class _DataPool* dp;
};

extern struct _SocketInitializer *SI;

#pragma pack(push)
#pragma pack(1)

struct UDPPacket
{
    enum {MAX_DATALENGTH = 512 - 12};
    char Reserved[3];//hxc
    DWORD TimeStamp;
    short DataLen;
    BYTE Data[1];
    //char Reserved[3];cxh
};

struct HeartBeat
{
};

#pragma pack(pop)

struct SockEventArg
{
    DWORD dwNumberOfBytesTransferred;
    int addrlen;
    sockaddr_in RemoteAddr;
    WSABUF* pBuffer;
    ULONG_PTR Param;
};

class __declspec(novtable) CSocketBase
{
    friend struct _SocketInitializer;
protected:
    SOCKET s;
protected:
    CSocketBase(EventHandler* InstHandler);
    virtual ~CSocketBase();
public:
    template<class T>
    static T* CreateSocket(EventHandler* InstHandler)
    {
        T* p = new T(InstHandler);
        p->Initialize();
        return p;
    }
    virtual int Bind(const struct sockaddr_in* name);
    virtual BOOL Initialize();
    virtual int Receive(void);
    virtual int SendTo(const BYTE* lpBuffer, DWORD dwBufferLen, const struct sockaddr_in *lpTo, DWORD dwFlags);
    virtual int Shutdown(int how);
    inline operator SOCKET();
    DECLARE_EVENT(OnRecv, EventHandler, SockEventArg);
    DECLARE_EVENT(OnSend, EventHandler, SockEventArg);
    DECLARE_EVENT(OnShutdown, EventHandler, SockEventArg);
protected:
    virtual bool onRecv(struct _OverlappedCtx* pCtx);
    virtual bool onSend(struct _OverlappedCtx* pCtx);
    static LPFN_ACCEPTEX pfnAcceptEx;
    static LPFN_GETACCEPTEXSOCKADDRS pfnGetAcceptExSocketaddrs;
    static LPFN_CONNECTEX pfnConnectEx;
    static LPFN_DISCONNECTEX pfnDisconnectEx;
};

class CUDPSocket : public CSocketBase
{
    friend CSocketBase;
    friend _SocketInitializer;
public:
    ~CUDPSocket();
    virtual int SendTo(const BYTE* lpBuffer, DWORD dwBufferLen, const struct sockaddr_in *lpTo, DWORD dwFlags);
protected:
    virtual BOOL Initialize();
    virtual bool onSend(struct _OverlappedCtx* pCtx);
    CUDPSocket(EventHandler* InstHandler);
};

class CTCPSocket : public CSocketBase
{
    friend CSocketBase;
protected:
    HANDLE hEventAccept;
    HANDLE hListenThread;
public:
    virtual ~CTCPSocket();
public:
    virtual BOOL Connect(const struct sockaddr_in* name, void* lpSendBuffer, DWORD dwSendDataLength);
    virtual BOOL Disconnect(void);
    virtual int Listen(int backlog);
    virtual int Send(const BYTE* lpBuffer, DWORD dwBufferLen, DWORD dwFlags);
    virtual BOOL PostAcceptOperation();
    DECLARE_EVENT(OnAccept, EventHandler, SockEventArg);
    DECLARE_EVENT(OnConn, EventHandler, SockEventArg);
    DECLARE_EVENT(OnDisconn, EventHandler, SockEventArg);
protected:
    CTCPSocket(EventHandler* InstHandler);
    virtual BOOL Initialize(void);
    bool onAccept(struct _OverlappedCtx* pCtx);
    bool onConn(struct _OverlappedCtx* pCtx);
    bool onDisconn(struct _OverlappedCtx* pCtx);
    static DWORD WINAPI ListenThread(PVOID pParam);
protected:
    void OnProxyRecv(SockEventArg* e);
};

};//namespace hxc

#endif //#if !defined _BACKDOOR_NETWORK_